
#include <material_editor/materialviewitems.h>
#include <material_editor/materialview.h>


/* ***********************************************
 *   CategoryItem
 * ***********************************************/


CategoryItem::CategoryItem (MaterialView* view, const Category& item)
  : BaseItem ()
  , _view (view)
  , _category(item)
  , _parent(0)
  , _editable(true)
{
  connect (&_category, SIGNAL(Changed()), this, SLOT(TriggerDataChanged()));
}

void CategoryItem::SetEditable(bool editable)
{
  _editable = editable;
}

bool CategoryItem::IsEditable() const
{
  return _editable;
}

bool CategoryItem::IsEmpty () const
{
  return GetNumberOfItems() == 0;
}

CategoryItem* CategoryItem::CreateNewItem (MaterialView* view, const Category& item)
{
  return new CategoryItem(view, item);
}

void CategoryItem::AddGroup (CategoryItem *item)
{
  Add(item);
  item->_parent = this;
  _children.push_back(item);
}

void CategoryItem::RemoveGroup (CategoryItem *item)
{
  Remove(item);
  _children.removeAll(item);
  item->_parent = 0;
}

CategoryItem* CategoryItem::Get (const QString& name)
{
  foreach (CategoryItem* child, _children)
    {
      if (name == child->GetName())
        {
          return child;
        }
    }

  CategoryItem* item = CreateNewItem(
                              _view,
                              Category (_category, name));
  AddGroup(item);
  return item;
}

void CategoryItem::Cleanup ()
{
  for (int i=0; i<_children.size(); i++)
    {
      _children[i]->Cleanup();
    }
  if (IsEmpty())
    {
      if (_parent)
        {
          _parent->RemoveGroup(this);
        }
    }
}

QVariant CategoryItem::GetData (int column, int role)
{
  if (column == 0 && role == Qt::DisplayRole) return QVariant (_category.GetHeadName());
  if (column == 0 && role == Qt::DecorationRole) return QVariant (QIcon (":/icons/media/category.png"));
  return QVariant ();
}

MaterialView* CategoryItem::GetView ()
{
  return _view;
}

Category& CategoryItem::GetCategory ()
{
  return _category;
}

const QString& CategoryItem::GetName () const
{
  return _category.GetHeadName();
}

void CategoryItem::EnableActions()
{
  if (_editable)
    {
      GetView ()->GetAction(MaterialView::Action_MaterialDataGroupRename)->setEnabled(true);
      GetView ()->GetAction(MaterialView::Action_MaterialDataGroupDelete)->setEnabled(true);
    }
}

bool CategoryItem::BuildMenu(QMenu *menu)
{
  if (_editable)
    {
      menu->addSeparator();
      menu->addAction (GetView ()->GetAction(MaterialView::Action_MaterialDataGroupRename));
      menu->addAction (GetView ()->GetAction(MaterialView::Action_MaterialDataGroupDelete));
    }
  return true;
}


/* ***********************************************
 *   MaterialDataItem
 * ***********************************************/

MaterialDataItem::MaterialDataItem (MaterialData* data, MaterialView* view)
  : BaseItem ()
  , _data (data)
  , _view (view)
{
  connect (data, SIGNAL(Changed()), this, SLOT(TriggerDataChanged()));
}


MaterialView* MaterialDataItem::GetView()
{
  return _view;
}

MaterialData* MaterialDataItem::GetMaterialData()
{
  return _data;
}


void MaterialDataItem::EnableActions()
{
  GetView()->GetAction(MaterialView::Action_MaterialDataRename)->setEnabled(true);
  GetView()->GetAction(MaterialView::Action_MaterialDataDelete)->setEnabled(true);
}


bool MaterialDataItem::BuildMenu(QMenu *menu)
{
  menu->addAction (GetView()->GetAction(MaterialView::Action_MaterialDataRename));
  menu->addAction (GetView()->GetAction(MaterialView::Action_MaterialDataDelete));

  return true;
}

/* ***********************************************
 *   TextureCategoryItem
 * ***********************************************/


TextureCategoryItem::TextureCategoryItem (MaterialView* view, const Category& item, bool editable)
  : CategoryItem(view, item)
{
  SetEditable(editable);
}

CategoryItem* TextureCategoryItem::CreateNewItem (MaterialView* view, const Category& item)
{
  return new TextureCategoryItem(view, item, true);
}


void TextureCategoryItem::EnableActions()
{
  GetView()->GetAction(MaterialView::Action_TextureAdd)->setEnabled(true);
  CategoryItem::EnableActions();
}


bool TextureCategoryItem::BuildMenu (QMenu* menu)
{
  menu->addAction (GetView ()->GetAction(MaterialView::Action_TextureAdd));
  return CategoryItem::BuildMenu(menu);
}




/* ***********************************************
 *   TextureItem
 * ***********************************************/

TextureItem::TextureItem (MaterialView* view, Texture* texture)
  : MaterialDataItem (texture, view)
  , _texture (texture)
{
  connect (texture, SIGNAL(NameChanged()), this, SLOT(TriggerDataChanged()));

  SetData(_texture);
}

Texture* TextureItem::GetTexture ()
{
  return _texture;
}

QVariant TextureItem::GetData (int column, int role)
{
  if (column == 0 && role == Qt::DisplayRole) return QVariant (_texture->GetFullname());
  if (column == 0 && role == Qt::DecorationRole) return QVariant (QIcon(":/icons/media/texture.png"));
  return QVariant ();
}

void TextureItem::EnableActions()
{
  GetView()->GetAction(MaterialView::Action_TextureEdit)->setEnabled(true);
  MaterialDataItem::EnableActions();
}

bool TextureItem::BuildMenu (QMenu* menu)
{
  menu->addAction (GetView()->GetAction(MaterialView::Action_TextureEdit));
  return MaterialDataItem::BuildMenu(menu);
}

void TextureItem::Trigger ()
{
  GetView()->GetAction(MaterialView::Action_TextureEdit)->trigger ();
}





/* ***********************************************
 *   ShaderCategoryItem
 * ***********************************************/


ShaderCategoryItem::ShaderCategoryItem (MaterialView* view, const Category& item, bool editable)
  : CategoryItem(view, item)
{
  SetEditable (editable);
}

CategoryItem* ShaderCategoryItem::CreateNewItem (MaterialView* view, const Category& item)
{
  return new ShaderCategoryItem(view, item, true);
}

void ShaderCategoryItem::EnableActions()
{
  GetView ()->GetAction(MaterialView::Action_ShaderAdd)->setEnabled(true);
  CategoryItem::EnableActions();
}

bool ShaderCategoryItem::BuildMenu (QMenu* menu)
{
  menu->addAction (GetView ()->GetAction(MaterialView::Action_ShaderAdd));
  return CategoryItem::BuildMenu(menu);
}


/* ***********************************************
 *   ShaderItem
 * ***********************************************/

ShaderItem::ShaderItem (MaterialView* view, Shader* shader)
  : MaterialDataItem (shader, view)
  , _shader (shader)
{
  connect (shader, SIGNAL(NameChanged()), this, SLOT(TriggerDataChanged()));

  SetData(_shader);
}

Shader* ShaderItem::GetShader ()
{
  return _shader;
}

QVariant ShaderItem::GetData (int column, int role)
{
  if (column == 0 && role == Qt::DisplayRole) return QVariant (_shader->GetFullname());
  if (column == 0 && role == Qt::DecorationRole)
    {
      switch (_shader->GetShaderType())
        {
        case ST_Vertex:
          return QVariant (QIcon(":/icons/media/vertex_shader.png"));

        case ST_Fragment:
          return QVariant (QIcon(":/icons/media/fragment_shader.png"));
        }
      return QVariant (QIcon(":/icons/media/text.png"));

    }
  return QVariant ();
}

void ShaderItem::EnableActions()
{
  GetView()->GetAction(MaterialView::Action_ShaderEdit)->setEnabled(true);
  GetView()->GetAction(MaterialView::Action_ShaderChangeType)->setEnabled(true);
  MaterialDataItem::EnableActions();
}

bool ShaderItem::BuildMenu (QMenu* menu)
{
  menu->addAction (GetView()->GetAction(MaterialView::Action_ShaderEdit));
  menu->addAction (GetView()->GetAction(MaterialView::Action_ShaderChangeType));
  return MaterialDataItem::BuildMenu(menu);
}

void ShaderItem::Trigger ()
{
  GetView()->GetAction(MaterialView::Action_ShaderEdit)->trigger ();
}



/* ***********************************************
 *   ProgramCategoryItem
 * ***********************************************/


ProgramCategoryItem::ProgramCategoryItem (MaterialView* view, const Category& item, bool editable)
  : CategoryItem(view, item)
{
  SetEditable (editable);
}

CategoryItem* ProgramCategoryItem::CreateNewItem (MaterialView* view, const Category& item)
{
  return new ProgramCategoryItem(view, item, true);
}

void ProgramCategoryItem::EnableActions()
{
  GetView ()->GetAction(MaterialView::Action_ProgramAdd)->setEnabled(true);
  CategoryItem::EnableActions();
}

bool ProgramCategoryItem::BuildMenu (QMenu* menu)
{
  menu->addAction (GetView ()->GetAction(MaterialView::Action_ProgramAdd));
  return CategoryItem::BuildMenu(menu);
}


/* ***********************************************
 *   ProgramItem
 * ***********************************************/

ProgramItem::ProgramItem (MaterialView* view, Program* program)
  : MaterialDataItem (program, view)
  , _program (program)
{
  connect (program, SIGNAL(NameChanged()), this, SLOT(TriggerDataChanged()));

  SetData(_program);
}

Program* ProgramItem::GetProgram ()
{
  return _program;
}

QVariant ProgramItem::GetData (int column, int role)
{
  if (column == 0 && role == Qt::DisplayRole) return QVariant (_program->GetFullname());
  if (column == 0 && role == Qt::DecorationRole) return QVariant (QIcon(":/icons/media/texture.png"));
  return QVariant ();
}

void ProgramItem::EnableActions()
{
  GetView()->GetAction(MaterialView::Action_ProgramEdit)->setEnabled(true);
  MaterialDataItem::EnableActions();
}

bool ProgramItem::BuildMenu (QMenu* menu)
{
  menu->addAction (GetView()->GetAction(MaterialView::Action_ProgramEdit));
  return MaterialDataItem::BuildMenu(menu);
}

void ProgramItem::Trigger ()
{
  GetView()->GetAction(MaterialView::Action_ProgramEdit)->trigger ();
}


/* ***********************************************
 *   EffectCategoryItem
 * ***********************************************/


EffectCategoryItem::EffectCategoryItem (MaterialView* view, const Category& item, bool editable)
  : CategoryItem(view, item)
{
  SetEditable (editable);
}

CategoryItem* EffectCategoryItem::CreateNewItem (MaterialView* view, const Category& item)
{
  return new EffectCategoryItem(view, item, true);
}

void EffectCategoryItem::EnableActions()
{
  GetView ()->GetAction(MaterialView::Action_EffectAdd)->setEnabled(true);
  CategoryItem::EnableActions();
}

bool EffectCategoryItem::BuildMenu (QMenu* menu)
{
  menu->addAction (GetView ()->GetAction(MaterialView::Action_EffectAdd));
  return CategoryItem::BuildMenu(menu);
}


/* ***********************************************
 *   EffectItem
 * ***********************************************/

EffectItem::EffectItem (MaterialView* view, Effect* effect)
  : MaterialDataItem (effect, view)
  , _effect (effect)
{
  connect (effect, SIGNAL(NameChanged()), this, SLOT(TriggerDataChanged()));

  SetData(_effect);
}

Effect* EffectItem::GetEffect ()
{
  return _effect;
}

QVariant EffectItem::GetData (int column, int role)
{
  if (column == 0 && role == Qt::DisplayRole) return QVariant (_effect->GetFullname());
  if (column == 0 && role == Qt::DecorationRole) return QVariant (QIcon(":/icons/media/texture.png"));
  return QVariant ();
}

void EffectItem::EnableActions()
{
  GetView()->GetAction(MaterialView::Action_EffectEdit)->setEnabled(true);
  MaterialDataItem::EnableActions();
}

bool EffectItem::BuildMenu (QMenu* menu)
{
  menu->addAction (GetView()->GetAction(MaterialView::Action_EffectEdit));
  return MaterialDataItem::BuildMenu(menu);
}

void EffectItem::Trigger ()
{
  GetView()->GetAction(MaterialView::Action_EffectEdit)->trigger ();
}




/* ***********************************************
 *   MaterialCategoryItem
 * ***********************************************/


MaterialCategoryItem::MaterialCategoryItem (MaterialView* view, const Category& item, bool editable)
  : CategoryItem(view, item)
{
  SetEditable (editable);
}

CategoryItem* MaterialCategoryItem::CreateNewItem (MaterialView* view, const Category& item)
{
  return new MaterialCategoryItem(view, item, true);
}

void MaterialCategoryItem::EnableActions()
{
  GetView ()->GetAction(MaterialView::Action_MaterialAdd)->setEnabled(true);
  CategoryItem::EnableActions();
}

bool MaterialCategoryItem::BuildMenu (QMenu* menu)
{
  menu->addAction (GetView ()->GetAction(MaterialView::Action_MaterialAdd));
  return CategoryItem::BuildMenu(menu);
}


/* ***********************************************
 *   MaterialItem
 * ***********************************************/

MaterialItem::MaterialItem (MaterialView* view, Material* material)
  : MaterialDataItem (material, view)
  , _material (material)
{
  connect (material, SIGNAL(NameChanged()), this, SLOT(TriggerDataChanged()));

  SetData(_material);
}

Material* MaterialItem::GetMaterial ()
{
  return _material;
}

QVariant MaterialItem::GetData (int column, int role)
{
  if (column == 0 && role == Qt::DisplayRole) return QVariant (_material->GetFullname());
  if (column == 0 && role == Qt::DecorationRole) return QVariant (QIcon(":/icons/media/texture.png"));
  return QVariant ();
}

void MaterialItem::EnableActions()
{
  GetView()->GetAction(MaterialView::Action_MaterialEdit)->setEnabled(true);
  MaterialDataItem::EnableActions();
}

bool MaterialItem::BuildMenu (QMenu* menu)
{
  menu->addAction (GetView()->GetAction(MaterialView::Action_MaterialEdit));
  return MaterialDataItem::BuildMenu(menu);
}

void MaterialItem::Trigger ()
{
  GetView()->GetAction(MaterialView::Action_MaterialEdit)->trigger ();
}




